﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Csla.Wpf;
using OpenExpressApp.MetaModel;
using System.ComponentModel;

namespace OpenExpressApp
{
    /// <summary>
    /// ObjectView的数据加载器
    /// </summary>
    public abstract class ViewDataLoaderBase : IViewDataLoader
    {
        protected CslaDataProvider _dataProvider;

        private ObjectView _view;

        public ViewDataLoaderBase(ObjectView view)
        {
            this._view = view;
            view.DataLoader = this;

            this.InitDataProvider();
        }

        public ObjectView View
        {
            get
            {
                return this._view;
            }
        }

        #region DataProvider

        /// <summary>
        /// 对应BOType的列表类型
        /// </summary>
        protected abstract Type FindQueryType();

        protected abstract string FactoryMethod { get; }

        protected CslaDataProvider DataProvider
        {
            get
            {
                return this._dataProvider;
            }
        }

        /// <summary>
        /// 初始化组件。
        /// </summary>
        private void InitDataProvider()
        {
            //生成列表界面
            this._dataProvider = this.CreateDataProvider();
            (this._dataProvider as ISupportInitialize).BeginInit();
            this._dataProvider.IsAsynchronous = true;
            this._dataProvider.ManageObjectLifetime = false;
            this._dataProvider.IsInitialLoadEnabled = false;
            this._dataProvider.DataChanged += new EventHandler(DataProvider_DataLoaded);
            (this._dataProvider as ISupportInitialize).EndInit();
        }

        /// <summary>
        /// 生成可使用的DataProvider
        /// </summary>
        /// <returns></returns>
        protected virtual CslaDataProvider CreateDataProvider()
        {
            return new CslaDataProvider();
        }

        #endregion

        #region AsyncGetObject Methods

        public void AsyncGetObject(params Object[] getListParam)
        {
            this.AsyncGetObject(FactoryMethod, getListParam);
        }

        public void AsyncGetObject(IQueryObject criteria)
        {
            this.AsyncGetObject(FactoryMethod, criteria);
        }

        public void AsyncGetObject(string getListMethod, IQueryObject criteria)
        {
            this.AsyncGetObject(getListMethod, new object[] { criteria });
        }

        public virtual void AsyncGetObject(string getListMethod, params Object[] getListParam)
        {
            using (this._dataProvider.DeferRefresh())
            {
                this._dataProvider.ObjectType = this.FindQueryType();
                this._dataProvider.FactoryMethod = getListMethod;
                this._dataProvider.FactoryParameters.Clear();
                foreach (var item in getListParam)
                {
                    this._dataProvider.FactoryParameters.Add(item);
                }
            }
        }

        #endregion

        #region Loading Data

        /// <summary>
        /// 表示当前是否正自在异步加载的状态
        /// </summary>
        public bool IsLoadingData
        {
            get
            {
                return this._dataProvider.IsBusy;
            }
        }

        public void CancelLoading()
        {
            this._dataProvider.Cancel();
        }

        /// <summary>
        /// 重新绑定View的数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DataProvider_DataLoaded(object sender, EventArgs e)
        {
            if (this._dataProvider.Error == null)
            {
                //重新绑定数据
                var asyncData = this._dataProvider.Data;

                var args = new DataLoadedEventArgs(asyncData);

                //这个事件的处理者，可能会对这个数据进行一些更改。
                this.OnDataLoaded(args);

                this._view.Data = args.Data;

                this.OnDataChanged(EventArgs.Empty);
            }
        }

        public event EventHandler<DataLoadedEventArgs> DataLoaded;

        /// <summary>
        /// 数据加载完成时，发生此事件。
        /// </summary>
        protected virtual void OnDataLoaded(DataLoadedEventArgs e)
        {
            if (this.DataLoaded != null)
            {
                this.DataLoaded(this, e);
            }
        }

        public event EventHandler DataChanged;

        /// <summary>
        /// 数据加载完成时，发生此事件。
        /// </summary>
        protected virtual void OnDataChanged(EventArgs e)
        {
            if (this.DataChanged != null)
            {
                this.DataChanged(this, e);
            }
        } 

        #endregion
    }
}
